﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WPFColorPickerLib;

namespace CSharp.Libs.WPF.UserControls
{
    /// <summary>
    /// Interaktionslogik für CSharp.xaml
    /// </summary>
    public partial class MapView : UserControl
    {
        #region declarations
        private MapViewViewModel _MVVM = null;
        
        Point? lastCenterPositionOnTarget;
        Point? lastMousePositionOnTarget;
        Point? lastDragPoint;
        #endregion



        #region constructor / terminator
        public MapView()
        {
            InitializeComponent();
        }
        #endregion



        #region private functions
        private void _Initialize(
            MapViewViewModel MVVM)
        {
            _MVVM = MVVM;
            DataContext = _MVVM;

            scrollViewer.ScrollChanged += OnScrollViewerScrollChanged;
            scrollViewer.MouseLeftButtonUp += OnMouseLeftButtonUp;
            scrollViewer.PreviewMouseLeftButtonUp += OnMouseLeftButtonUp;
            scrollViewer.PreviewMouseWheel += OnPreviewMouseWheel;

            scrollViewer.PreviewMouseLeftButtonDown += OnMouseLeftButtonDown;
            scrollViewer.MouseMove += OnMouseMove;

            slider.ValueChanged += OnSliderValueChanged;
        }
        #endregion



        #region events
        #region mouse dragging
        void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            //dragging around
            var mousePos = e.GetPosition(scrollViewer);
            if (mousePos.X <= scrollViewer.ViewportWidth && mousePos.Y < scrollViewer.ViewportHeight) //make sure we still can use the scrollbars
            {
                scrollViewer.Cursor = Cursors.SizeAll;
                lastDragPoint = mousePos;
                Mouse.Capture(scrollViewer);
            }
        }

        void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            scrollViewer.Cursor = Cursors.Arrow;
            scrollViewer.ReleaseMouseCapture();
            lastDragPoint = null;
        }

        void OnMouseMove(object sender, MouseEventArgs e)
        {
            //dragging around
            if(lastDragPoint.HasValue)
            {
                Point posNow = e.GetPosition(scrollViewer);

                double dX = posNow.X - lastDragPoint.Value.X;
                double dY = posNow.Y - lastDragPoint.Value.Y;

                lastDragPoint = posNow;

                scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset - dX);
                scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - dY);
            }
        }
        #endregion

        void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
        {
            lastMousePositionOnTarget = Mouse.GetPosition(imgTop);

            if(e.Delta > 0)
            {
                slider.Value += 0.1;
            }
            if(e.Delta < 0)
            {
                slider.Value -= 0.1;
            }

            e.Handled = true;
        }


        void OnSliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            scaleTransform.ScaleX = e.NewValue;
            scaleTransform.ScaleY = e.NewValue;

            var centerOfViewport = new Point(scrollViewer.ViewportWidth / 2, scrollViewer.ViewportHeight / 2);
            lastCenterPositionOnTarget = scrollViewer.TranslatePoint(centerOfViewport, imgTop);
        }

        void OnScrollViewerScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            if(e.ExtentHeightChange != 0 || e.ExtentWidthChange != 0)
            {
                Point? targetBefore = null;
                Point? targetNow = null;

                if(!lastMousePositionOnTarget.HasValue)
                {
                    if(lastCenterPositionOnTarget.HasValue)
                    {
                        var centerOfViewport = new Point(scrollViewer.ViewportWidth / 2, scrollViewer.ViewportHeight / 2);
                        Point centerOfTargetNow = scrollViewer.TranslatePoint(centerOfViewport, imgTop);

                        targetBefore = lastCenterPositionOnTarget;
                        targetNow = centerOfTargetNow;
                    }
                }
                else
                {
                    targetBefore = lastMousePositionOnTarget;
                    targetNow = Mouse.GetPosition(imgTop);

                    lastMousePositionOnTarget = null;
                }

                if(targetBefore.HasValue)
                {
                    double dXInTargetPixels = targetNow.Value.X - targetBefore.Value.X;
                    double dYInTargetPixels = targetNow.Value.Y - targetBefore.Value.Y;

                    double multiplicatorX = e.ExtentWidth / scrollViewer.ActualWidth;
                    double multiplicatorY = e.ExtentHeight / scrollViewer.ActualHeight;

                    double newOffsetX = scrollViewer.HorizontalOffset - dXInTargetPixels * multiplicatorX;
                    double newOffsetY = scrollViewer.VerticalOffset - dYInTargetPixels * multiplicatorY;

                    if(double.IsNaN(newOffsetX) || double.IsNaN(newOffsetY))
                    {
                        return;
                    }

                    scrollViewer.ScrollToHorizontalOffset(newOffsetX);
                    scrollViewer.ScrollToVerticalOffset(newOffsetY);
                }
            }
        }

        #region mouse position on map
        /// <summary>imgTop_PreviewMouseMove</summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <remarks>most important to give the current mouse x and y coordinates to the ViewModel</remarks>
        /// <history>03.08.2011</history>
        private void imgTop_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            Point MousePos = e.GetPosition(imgTop);

            _MVVM.CurrentX = (Int32)MousePos.X;
            _MVVM.CurrentY = (Int32)MousePos.Y;
        }

        private void imgTop_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            Point MousePos = e.GetPosition(imgTop);

            _MVVM.RightClickX = (Int32)MousePos.X;
            _MVVM.RightClickY = (Int32)MousePos.Y;
        }
        #endregion

        #region buttons
        private void btnSetBackgroundColor1_Click(object sender, RoutedEventArgs e)
        {
            ColorDialog colorDialog = new ColorDialog();
            colorDialog.SelectedColor = _MVVM.BackgroundColor1.Color;
            if ((bool)colorDialog.ShowDialog())
            {
                _MVVM.BackgroundColor1 = new SolidColorBrush((Color)ColorConverter.ConvertFromString(colorDialog.SelectedColor.ToString()));
            }
        }

        private void btnSetBackgroundColor2_Click(object sender, RoutedEventArgs e)
        {
            ColorDialog colorDialog = new ColorDialog();
            colorDialog.SelectedColor = _MVVM.BackgroundColor2.Color;
            if ((bool)colorDialog.ShowDialog())
            {
                _MVVM.BackgroundColor2 = new SolidColorBrush((Color)ColorConverter.ConvertFromString(colorDialog.SelectedColor.ToString()));
            }
        }
        #endregion
        #endregion



        #region interface
        #region properties
        #endregion

        #region methods
        public void Initialize(
            MapViewViewModel MVVM)
        {
            _Initialize(MVVM);
        }
        #endregion
        #endregion
    }
}
